//封装一个tcp服务器
#pragma once
#include "sock.hpp"
#include <iostream>
#include <string>
#include <functional>
#include <pthread.h>
#include <vector>

namespace ns_tcpserver
{
    //返回值为void 内部参数为Sock类型
    using func_t = std::function<void(int)>;

    class TcpServer; //前置声明一下

    struct ThreadData
    {
        int _sock;
        TcpServer* _tsr;
        ThreadData(int sock,TcpServer* tsr)
        :_sock(sock),_tsr(tsr)
        {}

        ThreadData(){}
    }; 

    class TcpServer
    {
    private:
        static void* ThreadRoutine(void* args)
        {
            pthread_detach(pthread_self());
            ThreadData* td = static_cast<ThreadData*>(args);
            td->_tsr->Excute(td->_sock);
            //执行完就关了，防止文件描述符泄露
            close(td->_sock);
            delete td;
            return nullptr;
        }


    public:
        TcpServer(const uint16_t& port,const std::string& ip = "0.0.0.0")
        {
            _listensock = _sock.CreateSocket();
            _sock.Bind(_listensock,port,ip);
            _sock.Listen(_listensock);
        }
        //绑定使用的函数
        void BindFunc(func_t func)
        {
            _funcs.push_back(func);
        }
        //执行函数
        void Excute(int sock)
        {
            for(auto& e:_funcs)
            {
                e(sock);
            }
        }
        void Start()
        {
            while(1)
            {
                uint16_t clientport;
                std::string clientip;
                int sock = _sock.Accept(_listensock,&clientip,&clientport);
                if(sock == -1)
                    continue;  //继续尝试连接
                logMessage(NORMAL,"accept success,sock:%d",sock);
                //创建线程和threaddata
                pthread_t t;
                ThreadData* td = new ThreadData(sock,this);
                pthread_create(&t,nullptr,ThreadRoutine,td);
            }
        }
        ~TcpServer()
        {
            if (_listensock >= 0)
                close(_listensock);
        }
    private:
        int _listensock;
        Sock _sock; //用封装好的
        //func_t _func;
        //可以执行多个函数的版本
        std::vector<func_t> _funcs;
    };
}